/*
 ** writen by hanv
 ** n2.vietha@gmail.com
 */
package vn.vng.research.fsd.da;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;

import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.document.Field;
import org.apache.lucene.document.NumericField;
import org.apache.lucene.index.FieldInfo.IndexOptions;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexWriterConfig;
import org.apache.lucene.index.IndexWriterConfig.OpenMode;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.FSDirectory;
import org.apache.lucene.util.Version;
import org.apache.lucene.document.Document;

import vn.vng.research.fsd.Configuration;

public class ProfilesDA {
	private static String PROFILES_PATH = Configuration.loadProfilesPath();
	private static String INDEX_PATH = Configuration.loadIndexPath();;
	private static final String SPLITTER = "\\t+";
	private static final String[] PROFILE_FORMAT = { "uid", "unknown",
			"username", "email", "displayname", "location", "unknown",
			"education", "education", "nationality", "unknown", "unknown",
			"unknown", "unknown", "unknown" };

	private static long profilesCount;

	private static final char[] MARKED_CHARS = { 'á', 'à', 'ạ', 'ã', 'ả', 'ă',
			'ắ', 'ằ', 'ặ', 'ẵ', 'ẳ', 'â', 'ấ', 'ầ', 'ậ', 'ẫ', 'ẩ', 'đ', 'é',
			'è', 'ẹ', 'ẽ', 'ẻ', 'ê', 'ế', 'ề', 'ệ', 'ễ', 'ể', 'í', 'ì', 'ị',
			'ĩ', 'ỉ', 'ó', 'ò', 'ọ', 'õ', 'ỏ', 'ô', 'ố', 'ồ', 'ộ', 'ỗ', 'ổ',
			'ơ', 'ớ', 'ờ', 'ợ', 'ỡ', 'ở', 'ú', 'ù', 'ụ', 'ũ', 'ủ', 'ư', 'ứ',
			'ừ', 'ự', 'ữ', 'ử', 'ý', 'ỳ', 'ỵ', 'ỹ', 'ỷ' };

	private static final char[] UNMARKED_CHARS = { 'a', 'a', 'a', 'a', 'a',
			'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'd',
			'e', 'e', 'e', 'e', 'e', 'e', 'e', 'e', 'e', 'e', 'e', 'i', 'i',
			'i', 'i', 'i', 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'o',
			'o', 'o', 'o', 'o', 'o', 'o', 'o', 'u', 'u', 'u', 'u', 'u', 'u',
			'u', 'u', 'u', 'u', 'u', 'y', 'y', 'y', 'y', 'y' };

	public static void fetchAndIndex() {
		try {
			Directory dir = FSDirectory.open(new File(INDEX_PATH));
			Analyzer analyzer = new StandardAnalyzer(Version.LUCENE_31);
			IndexWriterConfig config = new IndexWriterConfig(Version.LUCENE_31,
					analyzer);
			// setup config mode to create
			config.setOpenMode(OpenMode.CREATE);
			IndexWriter writer = new IndexWriter(dir, config);

			System.out.println("Started indexing profiles from: "
					+ PROFILES_PATH + " to: " + INDEX_PATH + ".");
			long start = System.currentTimeMillis();
			profilesCount = 0;
			indexProfiles(writer, new File(PROFILES_PATH));
			long end = System.currentTimeMillis();

			System.out
					.println("Indexed " + profilesCount
							+ " profile(s) successfully after " + (end - start)
							+ "ms.");

			writer.close();
		} catch (Exception e) {
			// TODO: handle exception
			e.printStackTrace();
		}
	}

	private static void indexProfiles(IndexWriter writer, File profilesPath)
			throws Exception {
		if (profilesPath.canRead()) {
			if (profilesPath.isDirectory()) {
				String[] files = profilesPath.list();
				// an IO error could occur
				if (files != null) {
					for (int i = 0; i < files.length; i++) {
						indexProfiles(writer, new File(profilesPath, files[i]));
					}
				}
			} else {
				FileInputStream fis;
				try {
					fis = new FileInputStream(profilesPath);
				} catch (FileNotFoundException fnfe) {
					// at least on windows, some temporary files raise this
					// exception with an "access denied" message
					// checking if the file can be read doesn't help
					return;
				}

				try {
					BufferedReader br = new BufferedReader(
							new InputStreamReader(fis, "UTF-8"));
					String line = null;
					while ((line = br.readLine()) != null) {
						Document doc = new Document();

						// TODO: do sth with line
						String[] elements = line.split(SPLITTER);

						// uid at 0
						int uid = Integer.parseInt(elements[0]);
						NumericField uidField = new NumericField(
								PROFILE_FORMAT[0], Field.Store.YES, true);
						uidField.setIntValue(uid);
						doc.add(uidField);

						// username at 2
						Field usernameField = new Field(PROFILE_FORMAT[2],
								elements[2], Field.Store.YES,
								Field.Index.NOT_ANALYZED_NO_NORMS);
						usernameField.setIndexOptions(IndexOptions.DOCS_ONLY);
						doc.add(usernameField);

						// email at 3
						Field emailField = new Field(PROFILE_FORMAT[3],
								elements[3], Field.Store.YES,
								Field.Index.NOT_ANALYZED_NO_NORMS);
						emailField.setIndexOptions(IndexOptions.DOCS_ONLY);
						doc.add(emailField);

						// display name at 4
						Field displaynameField = new Field(PROFILE_FORMAT[4],
								elements[4], Field.Store.YES,
								Field.Index.ANALYZED);
						doc.add(displaynameField);

						// location at 5
						// education at 7
						String schoolName = inputFilter(elements[7].split(",")[0]);
						int education = SchoolRefinerDA.getID(schoolName);
						NumericField educationField = new NumericField(
								PROFILE_FORMAT[7], Field.Store.YES,true);
						educationField.setIntValue(education);
						doc.add(educationField);
						// nationality at 9

						// profile count ++
						profilesCount++;
						if (writer.getConfig().getOpenMode() == OpenMode.CREATE) {
							// New index, so we just add the document (no old
							// document can be there):
							writer.addDocument(doc);
						} else {
							// Existing index (an old copy of this document may
							// have
							// been indexed) so
							// we use updateDocument instead to replace the old
							// one
							// matching the exact
							// path, if present:

							// writer.updateDocument(new Term("path",
							// file.getPath()), doc);

							// chua viet update
							throw new Exception("Update index is unhandled");
						}
					}

				} finally {
					fis.close();
				}

			}
		}
	}

	private static String inputFilter(String in){
		String out = in.replaceAll("\\s+", "");
		out = out.toLowerCase();
		for (int i=0; i< MARKED_CHARS.length; i++){			
			out = out.replace(MARKED_CHARS[i], UNMARKED_CHARS[i]);
		}
		return out;
	}

	public static String getPROFILES_PATH() {
		return PROFILES_PATH;
	}

	public static void setPROFILES_PATH(String pROFILES_PATH) {
		PROFILES_PATH = pROFILES_PATH;
	}

	public static String getINDEX_PATH() {
		return INDEX_PATH;
	}

	public static void setINDEX_PATH(String iNDEX_PATH) {
		INDEX_PATH = iNDEX_PATH;
	}
	
	
	
}
